package com.danciyixue.boot.dcyx.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.danciyixue.boot.dcyx.mapper.UserStudyRecordsMapper;
import com.danciyixue.boot.dcyx.service.UserStudyRecordsService;
import com.danciyixue.boot.dcyx.model.entity.UserStudyRecords;
import com.danciyixue.boot.dcyx.model.form.UserStudyRecordsForm;
import com.danciyixue.boot.dcyx.model.form.UserStudyRecordsUpdateForm;
import com.danciyixue.boot.dcyx.model.query.UserStudyRecordsQuery;
import com.danciyixue.boot.dcyx.model.vo.UserStudyRecordsVO;
import com.danciyixue.boot.dcyx.model.vo.WordsVO;
import com.danciyixue.boot.dcyx.service.UnitsService;
import com.danciyixue.boot.dcyx.service.WordsService;
import com.danciyixue.boot.dcyx.converter.UserStudyRecordsConverter;
import com.danciyixue.boot.core.security.util.SecurityUtils;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.ArrayList;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.danciyixue.boot.dcyx.model.entity.Units;
import com.danciyixue.boot.dcyx.model.entity.Words;

/**
 * 用户学习记录服务实现类
 *
 * @author youlaitech
 * @since 2025-06-15 17:26
 */
@Service
@DS("dcyx")
@RequiredArgsConstructor
public class UserStudyRecordsServiceImpl extends ServiceImpl<UserStudyRecordsMapper, UserStudyRecords> implements UserStudyRecordsService {

    private final UserStudyRecordsConverter userStudyRecordsConverter;
    private final UnitsService unitsService;
    private final WordsService wordsService;

    /**
    * 获取用户学习记录分页列表
    *
    * @param queryParams 查询参数
    * @return {@link IPage<UserStudyRecordsVO>} 用户学习记录分页列表
    */
    @Override
    public IPage<UserStudyRecordsVO> getUserStudyRecordsPage(UserStudyRecordsQuery queryParams) {
        Page<UserStudyRecordsVO> pageVO = this.baseMapper.getUserStudyRecordsPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        return pageVO;
    }
    
    /**
     * 获取用户学习记录表单数据
     *
     * @param id 用户学习记录ID
     * @return 用户学习记录表单数据
     */
    @Override
    public UserStudyRecordsForm getUserStudyRecordsFormData(Long id) {
        UserStudyRecords entity = this.getById(id);
        return userStudyRecordsConverter.toForm(entity);
    }
    
    /**
     * 新增用户学习记录
     *
     * @param formData 用户学习记录表单对象
     * @return 是否新增成功
     */
    @Override
    public boolean saveUserStudyRecords(UserStudyRecordsForm formData) {
        UserStudyRecords entity = userStudyRecordsConverter.toEntity(formData);
        return this.save(entity);
    }
    
    /**
     * 更新用户学习记录
     *
     * @param id   用户学习记录ID
     * @param formData 用户学习记录表单对象
     * @return 是否修改成功
     */
    @Override
    public boolean updateUserStudyRecords(Long id,UserStudyRecordsForm formData) {
        UserStudyRecords entity = userStudyRecordsConverter.toEntity(formData);
        return this.updateById(entity);
    }

    /**
     * 新增OR修改用户学习记录
     *
     * @param formData 用户学习记录更新表单对象
     * @return 是否操作成功
     */
    @Override
    public boolean saveOrUpdateUserStudyRecords(UserStudyRecordsUpdateForm formData) {
        // 参数校验
        Assert.notNull(formData, "表单数据不能为空");
        Assert.notNull(formData.getWordId(), "单词ID不能为空");
        Assert.notNull(formData.getStatus(), "状态不能为空");
        Assert.notBlank(formData.getSource(), "来源不能为空");
        Assert.notBlank(formData.getSourceFrom(), "来源字段不能为空");

        // 获取当前登录用户ID
        Long currentUserId = SecurityUtils.getUserId();
        Assert.notNull(currentUserId, "用户未登录");

        // 根据单词ID查询单词信息，获取unitId和programId
        Words word = wordsService.getById(formData.getWordId());
        Assert.notNull(word, "单词信息不存在");

        // 根据用户ID、单词ID、来源和来源字段查找现有记录
        UserStudyRecords existingRecord = this.baseMapper.findByUserIdAndWordIdAndSourceAndSourceFrom(
                currentUserId, formData.getWordId(), formData.getSource(), formData.getSourceFrom());

        if (existingRecord != null) {
            // 更新现有记录
            existingRecord.setStatus(formData.getStatus());
            existingRecord.setUnitId(word.getUnitId());
            existingRecord.setProgramId(word.getProgramId());
            existingRecord.setUpdateUser(currentUserId);
            return this.updateById(existingRecord);
        } else {
            // 创建新记录
            UserStudyRecords newRecord = new UserStudyRecords();
            newRecord.setUserId(currentUserId);
            newRecord.setWordId(formData.getWordId());
            newRecord.setUnitId(word.getUnitId());
            newRecord.setProgramId(word.getProgramId());
            newRecord.setStatus(formData.getStatus());
            newRecord.setSource(formData.getSource());
            newRecord.setSourceFrom(formData.getSourceFrom());
            newRecord.setCreateUser(currentUserId);
            newRecord.setUpdateUser(currentUserId);
            return this.save(newRecord);
        }
    }

    /**
     * 删除用户学习记录
     *
     * @param ids 用户学习记录ID，多个以英文逗号(,)分割
     * @return 是否删除成功
     */
    @Override
    public boolean deleteUserStudyRecordss(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的用户学习记录数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        return this.removeByIds(idList);
    }

    /**
     * 获取用户需要复习的单词列表
     *
     * @param programId 教材ID，必须
     * @param unitId 单元ID，可选，如果为null则查询所有单元
     * @param source 来源，必须，取值有 dcjy、dctx、dcmx
     * @return 需要复习的单词列表
     */
    @Override
    public List<WordsVO> getReviewWords(Long programId, Long unitId, String source) {
        // 参数校验
        Assert.notNull(programId, "教材ID不能为空");
        Assert.notBlank(source, "来源不能为空");

        // 获取当前登录用户ID
        Long currentUserId = SecurityUtils.getUserId();
        Assert.notNull(currentUserId, "用户未登录");

        // 计算目标单元ID列表
        List<Long> unitIds = new ArrayList<>();
        if (ObjectUtil.isNotNull(unitId)) {
            // 如果指定了单元ID，只查询该单元
            unitIds.add(unitId);
        } else {
            // 如果没有指定单元ID，查询该教材下的所有单元
            LambdaQueryWrapper<Units> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Units::getProgramId, programId)
                        .eq(Units::getStatus, 1); // 假设状态1表示有效
            List<Units> units = unitsService.list(queryWrapper);
            unitIds = units.stream()
                          .map(Units::getId)
                          .collect(Collectors.toList());
        }

        // 如果没有找到任何单元，返回空列表
        if (unitIds.isEmpty()) {
            return new ArrayList<>();
        }

        // 调用Mapper查询需要复习的单词
        return this.baseMapper.getReviewWords(currentUserId, programId, unitIds, source);
    }

}
